package com.artfii.fluentsql.core.jdbc;

import com.artfii.fluentsql.core.exception.FluentSqlException;

import javax.sql.DataSource;
import java.sql.*;
import java.util.*;
import java.util.concurrent.Executor;


/**
 * 包装一下Connection,交给数连接沲去实现
 */
abstract class WrappedConnection implements Connection {
    protected DataSource master;
    protected List<DataSource> slaveList;
    protected Connection jdbcConnection;

    private final Set<Statement> statements = new HashSet<>();

    public WrappedConnection() {
    }

    public WrappedConnection(DataSource master) {
        this.master = master;
    }

    public WrappedConnection(DataSource masterDs, List<DataSource> slaveList) {
        this.master = masterDs;
        this.slaveList = slaveList;
    }

    /**
     * 取得当前Connection
     * @return
     */
    public abstract Connection getCurrentConnection(boolean isUpdate);

    @Override
    public Statement createStatement() throws SQLException {
        return jdbcConnection.createStatement();
    }

    @Override
    public PreparedStatement prepareStatement(String sql) throws SQLException {
        return jdbcConnection.prepareStatement(sql);
    }

    @Override
    public CallableStatement prepareCall(String sql) throws SQLException {
        return jdbcConnection.prepareCall(sql);
    }

    @Override
    public String nativeSQL(String sql) throws SQLException {
        return jdbcConnection.nativeSQL(sql);
    }

    @Override
    public void setAutoCommit(boolean autoCommit) throws SQLException {
        jdbcConnection.setAutoCommit(autoCommit);
    }

    @Override
    public boolean getAutoCommit() {
        try {
            return (null != jdbcConnection && jdbcConnection.getAutoCommit());
        } catch (SQLException e) {
            throw new FluentSqlException(e);
        }
    }

    @Override
    public void commit() throws SQLException {
        jdbcConnection.commit();
    }

    @Override
    public void rollback() throws SQLException {
        jdbcConnection.rollback();
    }

    @Override
    public void close() throws SQLException {
        jdbcConnection.close();
    }

    @Override
    public boolean isClosed(){
        try {
            return (null ==jdbcConnection || jdbcConnection.isClosed());
        } catch (SQLException e) {
            throw new FluentSqlException("JDBC connection is CLOSED.",e);
        }
    }

    @Override
    public DatabaseMetaData getMetaData() throws SQLException {
        return jdbcConnection.getMetaData();
    }

    @Override
    public void setReadOnly(boolean readOnly)  {
        try {
            jdbcConnection.setReadOnly(readOnly);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public boolean isReadOnly(){
        try {
            return jdbcConnection.isReadOnly();
        } catch (SQLException e) {
            return false;
        }
    }

    @Override
    public void setCatalog(String catalog) throws SQLException {
        jdbcConnection.setCatalog(catalog);
    }

    @Override
    public String getCatalog() throws SQLException {
        return jdbcConnection.getCatalog();
    }

    @Override
    public void setTransactionIsolation(int level)  {
        try {
            jdbcConnection.setTransactionIsolation(level);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public int getTransactionIsolation()  {
        try {
           return jdbcConnection.getTransactionIsolation();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public SQLWarning getWarnings() throws SQLException {
        return jdbcConnection.getWarnings();
    }

    @Override
    public void clearWarnings() throws SQLException {
        jdbcConnection.clearWarnings();
    }

    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
        return jdbcConnection.createStatement(resultSetType, resultSetConcurrency);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
        return jdbcConnection.prepareStatement(sql, resultSetType, resultSetConcurrency);
    }

    @Override
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
        return jdbcConnection.prepareCall(sql, resultSetType, resultSetConcurrency);
    }

    @Override
    public Map<String, Class<?>> getTypeMap() throws SQLException {
        return jdbcConnection.getTypeMap();
    }

    @Override
    public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
        jdbcConnection.setTypeMap(map);
    }

    @Override
    public void setHoldability(int holdability) throws SQLException {
        jdbcConnection.setHoldability(holdability);
    }

    @Override
    public int getHoldability() throws SQLException {
        return jdbcConnection.getHoldability();
    }

    @Override
    public Savepoint setSavepoint() throws SQLException {
        return jdbcConnection.setSavepoint();
    }

    @Override
    public Savepoint setSavepoint(String name) throws SQLException {
        return jdbcConnection.setSavepoint(name);
    }

    @Override
    public void rollback(Savepoint savepoint) throws SQLException {
        jdbcConnection.rollback(savepoint);
    }

    @Override
    public void releaseSavepoint(Savepoint savepoint) throws SQLException {
        jdbcConnection.releaseSavepoint(savepoint);
    }

    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
        return jdbcConnection.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
        return jdbcConnection.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
    }

    @Override
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
        return jdbcConnection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
        return jdbcConnection.prepareStatement(sql, autoGeneratedKeys);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
        return jdbcConnection.prepareStatement(sql, columnIndexes);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
        return jdbcConnection.prepareStatement(sql, columnNames);
    }

    @Override
    public Clob createClob() throws SQLException {
        return jdbcConnection.createClob();
    }

    @Override
    public Blob createBlob() throws SQLException {
        return jdbcConnection.createBlob();
    }

    @Override
    public NClob createNClob() throws SQLException {
        return jdbcConnection.createNClob();
    }

    @Override
    public SQLXML createSQLXML() throws SQLException {
        return jdbcConnection.createSQLXML();
    }

    @Override
    public boolean isValid(int timeout) throws SQLException {
        return jdbcConnection.isValid(timeout);
    }

    @Override
    public void setClientInfo(String name, String value) throws SQLClientInfoException {
        jdbcConnection.setClientInfo(name, value);
    }

    @Override
    public void setClientInfo(Properties properties) throws SQLClientInfoException {
        jdbcConnection.setClientInfo(properties);
    }

    @Override
    public String getClientInfo(String name) throws SQLException {
        return jdbcConnection.getClientInfo(name);
    }

    @Override
    public Properties getClientInfo() throws SQLException {
        return jdbcConnection.getClientInfo();
    }

    @Override
    public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
        return jdbcConnection.createArrayOf(typeName, elements);
    }

    @Override
    public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
        return jdbcConnection.createStruct(typeName, attributes);
    }

    @Override
    public void setSchema(String schema) throws SQLException {
        jdbcConnection.setSchema(schema);
    }

    @Override
    public String getSchema() throws SQLException {
        return jdbcConnection.getSchema();
    }

    @Override
    public void abort(Executor executor) throws SQLException {
        jdbcConnection.abort(executor);
    }

    @Override
    public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
        jdbcConnection.setNetworkTimeout(executor, milliseconds);
    }

    @Override
    public int getNetworkTimeout() throws SQLException {
        return jdbcConnection.getNetworkTimeout();
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return jdbcConnection.unwrap(iface);
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return jdbcConnection.isWrapperFor(iface);
    }
}
